﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Ionic.Zip;

namespace EpubSqueaker
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		public delegate void UpdateDirectoryDelegate();
		private IEnumerator<string> CurrentDir = null;
		private int currentIndex = 0;

		public MainWindow()
		{
			InitializeComponent();
			Progress.Visibility = System.Windows.Visibility.Hidden;
			RunModeDir.IsChecked = true;
		}

		private void btnGo_Click(object sender, RoutedEventArgs e)
		{
			if (RunModeFile.IsChecked == true)
			{
				windowInitialize();

				var dialog = new Microsoft.Win32.OpenFileDialog();
				var dialogResult = dialog.ShowDialog();
				if (dialogResult == true)
				{
					updateFile(dialog.FileName);
					windowFinalize(true);
				}
				else
				{
					windowFinalize(false);
				}
			}
			else if (RunModeDir.IsChecked == true)
			{
				var dialog = new System.Windows.Forms.FolderBrowserDialog();
				var dialogResult = dialog.ShowDialog();
				if (dialogResult == System.Windows.Forms.DialogResult.OK)
				{
					string bookPath = dialog.SelectedPath;

					var useSubdirs = (RunModeSubDirs.IsChecked == true) ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly;
					var allFiles = Directory.EnumerateFiles(bookPath, "*.epub", useSubdirs);
					CurrentDir = allFiles.GetEnumerator();
					windowInitialize(allFiles.Count());
					
					btnGo.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new UpdateDirectoryDelegate(updateNextFile));
				}
				else
				{
					windowInitialize();
					windowFinalize(false);
				}
			}
			else
			{
				// Nothing is checked. This is a problem.
				throw new ApplicationException("No button is selected - how?");
			}
		}

		private void chkTool_Checked(object sender, RoutedEventArgs e)
		{
			bool isButtonEnabled = false;
			foreach (var tool in gridTools.Children)
			{
				if ((tool is CheckBox) && (((CheckBox)tool).IsChecked == true))
				{
					isButtonEnabled = true;
					break;
				}
			}
			btnGo.IsEnabled = isButtonEnabled;
		}

		private void btnRunMode_Checked(object sender, RoutedEventArgs e)
		{
			RunModeSubDirs.IsEnabled = (RunModeDir.IsChecked == true);
			ToolBreakPages.IsEnabled = (RunModeFile.IsChecked == true);
			if (!ToolBreakPages.IsEnabled)
				ToolBreakPages.IsChecked = false;
		}

		private void updateNextFile()
		{
			if (CurrentDir != null)
			{
				updateFile(CurrentDir.Current);

				if (CurrentDir.MoveNext())
				{
					btnGo.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.SystemIdle,
						new UpdateDirectoryDelegate(this.updateNextFile));
				}
				else
				{
					CurrentDir = null;
					windowFinalize(true);
				}
			}
		}

		#region Progress area update methods
		private void windowInitialize()
		{
			btnGo.IsEnabled = false;
			btnGo.Content = "Running";

			Progress.Visibility = System.Windows.Visibility.Visible;
			ProgressFile.Text = "";
			UpdateFile.Text = "";

			currentIndex = 0;
			progressBar1.Minimum = 0;
			//progressBar1.IsIndeterminate = true;
		}

		private void windowInitialize(int maxCount)
		{
			windowInitialize();
			//progressBar1.IsIndeterminate = false;
			progressBar1.Maximum = maxCount;
		}

		private void progressUpdateStart(string filename)
		{
			ProgressFile.Text = "Processing file: " + filename;
		}

		private void progressUpdateFinish(string filename, bool isUpdated)
		{
			ProgressFile.Text = "Processed file: " + filename;
			if (isUpdated)
			{
				UpdateFile.Text = "Last updated file: " + filename;
			}
			currentIndex++;
			progressBar1.Value = currentIndex;
		}

		private void windowFinalize(bool success)
		{
			if (success)
			{
				ProgressFile.Text = "Processing complete.";
			}
			else
			{
				ProgressFile.Text = "Processing canceled.";
			}

			btnGo.Content = "Go";
			btnGo.IsEnabled = true;
			progressBar1.IsIndeterminate = false;
			progressBar1.Value = progressBar1.Maximum;
		}
		#endregion

		private void updateFile(string file)
		{
			if (file == null)
				return;

			progressUpdateStart(file);
			bool isUpdated = false;

			// Don't need to check for any tools being set here - we disable
			// the button if they aren't.
			using (ZipFile zip = ZipFile.Read(file))
			{
				if (ToolCovers.IsChecked == true)
				{
					isUpdated = NookTools.UpdateCoverMetadata(zip) || isUpdated;
				}
				if (ToolStripBookmarks.IsChecked == true)
				{
					isUpdated = NookTools.RemoveCalibreBookmarks(zip) || isUpdated;
				}
				if (ToolBreakPages.IsChecked == true)
				{
					var splitter = new XhtmlSplitter(zip);
					isUpdated = splitter.SplitXhtmlFiles() || isUpdated;
				}
			}
			progressUpdateFinish(file, isUpdated);
		}
	}
}
